#include "QueryResult.h"

void QueryResult::calcNextTripel() {
    _isEmpty = true;
    while (_currentBlockId < DiscManager::getDiscSize()) {
        if (!_currentBlock)
            _currentBlock = BufferManager::pinBlock(_currentBlockId);
        if (_currentBlock->isFree()) {
            BufferManager::unpinBlock(_currentBlockId);
            _currentBlock = NULL;
            _currentBlockId++;
            break;
        }
        uShort rowCount = _currentBlock->getRowCount();
        while (_currentRowId < rowCount) {
            _currentRow = _currentBlock->getRow(_currentRowId);
            byte a = _currentRow.header.bytes[0];
            if ((_currentRow.header.bytes[0] & M_1011_x4) == 0x90) {
                _isEmpty = false;
                if (_subjectIdBytes) {
                    if (!equalBytes(_subjectIdBytes, _currentRow.bytes, 5))
                        _isEmpty = true;
                }
                if (!_isEmpty && _predicateIdBytes) {
                    if (!equalBytes(_predicateIdBytes, _currentRow.bytes + 5, 5))
                        _isEmpty = true;
                }
                if (!_isEmpty && _objectIdBytes) {
                    if (!equalBytes(_objectIdBytes, _currentRow.bytes + 10, 5))
                        _isEmpty = true;
                }
                if (!_isEmpty) {
                    return;
                }
            }
            _currentRowId++;
        }
        BufferManager::unpinBlock(_currentBlockId);
        _currentBlock = NULL;
        _currentBlockId++;
        _currentRowId = 0;
    }
    _currentBlockId = 0;
    _currentRowId = 0;
}

QueryResult::QueryResult() {
    _currentBlockId = 0;
    _currentRowId = 0;
    _currentBlock = NULL;
    _subjectIdBytes = NULL;
    _predicateIdBytes = NULL;
    _objectIdBytes = NULL;
    calcNextTripel();
}

QueryResult::QueryResult(sTripel tripel) {
    _currentBlockId = 0;
    _currentRowId = 0;
    _currentBlock = NULL;
    _subjectIdBytes = NULL;
    _predicateIdBytes = NULL;
    _objectIdBytes = NULL;
    _isEmpty = false;
    if (!tripel.subject.empty()) {
        try {
            sSubjectId subjectId = SubjectManager::findSubject(tripel.subject);
            _subjectIdBytes = new byte[5];
            int3ToBytes(_subjectIdBytes, subjectId.blockId);
            int2ToBytes(_subjectIdBytes + 3, subjectId.rowId);
        }
        catch (Error) {
            _isEmpty = true; //subject existiert nicht
            return;
        }
    }
    if (!_isEmpty && !tripel.predicate.empty()) {
        try {
            sSubjectId predicateId = PredicateManager::findPredicate(tripel.predicate);
            _predicateIdBytes = new byte[5];
            int3ToBytes(_predicateIdBytes, predicateId.blockId);
            int2ToBytes(_predicateIdBytes + 3, predicateId.rowId);
        }
        catch (Error) {
            _isEmpty = true; //predicate existiert nicht
            return;
        }
    }
    if (!_isEmpty && !tripel.object.empty()) {
        try {
            sSubjectId objectId = SubjectManager::findSubject(tripel.object);
            _objectIdBytes = new byte[5];
            int3ToBytes(_objectIdBytes, objectId.blockId);
            int2ToBytes(_objectIdBytes + 3, objectId.rowId);
        }
        catch (Error) {
            _isEmpty = true; //object existiert nicht
            return;
        }
    }
    if (!_isEmpty) {
        calcNextTripel();
    }
}


QueryResult::QueryResult(const string& message) {
    _message = message;
}


QueryResult::~QueryResult() {
    if (_currentBlock) {
        BufferManager::unpinBlock(_currentBlockId);
        _currentBlock = 0;
    }
}


sTripel QueryResult::getNextResult() {
    if (_isEmpty)
        throw - 1;
    /*Ausgabe des naechsten tripels*/
    sTripel tripel = TripelManager::getTripel(_currentRow.header.valueId);
    _currentRowId++;
    /*next tripel*/
    calcNextTripel();
    return tripel;
}


bool QueryResult::isEmpty() {
    return _isEmpty;
}


string QueryResult::getMessage() {
    return _message;
}
